
#include <math.h>
#include <algorithm>

#include <boost/bind.hpp>

#include "winfunctions.h"

AbstractWinFunction::~AbstractWinFunction(){};


void AbstractWinFunction::addRef(void)
{
  ++ref;
};

void AbstractWinFunction::release(void)
{
  if (--ref == 0)
    delete this;
};

CompositeWinFunction::~CompositeWinFunction(){};

double CompositeWinFunction::operator()(double i, double w) const
{
  double result=1;
  const_iterator func = functions.begin();

  while(func != end() )
  {
    result *= (*(*func))(i,w);
    ++func;
  }
    return result;
};

void CompositeWinFunction::addFunction(WinFuncPtr function)
{
  functions.push_front(function);
};

void CompositeWinFunction::delFunction( const char* name )
{
  delFunction( find(name) );
};

void CompositeWinFunction::delFunction( const_iterator it )
{
};

//Auxilary function for searching.
const bool equivalence( const WinFuncPtr wf1, const char *name)
{
  return wf1->getName().compare( name ) == 0 ? true : false ;
};

CompositeWinFunction::const_iterator CompositeWinFunction::find( const char* name ) const
{
  return std::find_if( functions.begin(),
		       functions.end(),
		       boost::bind(&equivalence, _1, name) );
};

BufferedWinFunction::~BufferedWinFunction(){};

double BufferedWinFunction::operator()(double i, double w) const
{
  return buffer[i];
};

void BufferedWinFunction::init(double w)
{
  buffer.resize(w);

  for( size_t i=0; i<w; i++)
    buffer[i] = (*function)(i,w);
};

  static WindowFuncFactory& Instance();

const WinFuncPtr WindowFuncFactory::getFunction( const char* name )
{
  const_iterator it = std::find_if( functions.begin(),
		       functions.end(),
		       boost::bind(&equivalence, _1, name) );
  return ( it == functions.end() )? WinFuncPtr() : *it ;
};

WinFuncPtr WindowFuncFactory::getBufferedFunction( const char* name )
{
  WinFuncPtr func = getFunction( name );
  return (func.get() == NULL) ? func : new BufferedWinFunction(func);
};

WindowFuncFactory::iterator WindowFuncFactory::registerFunction( WinFuncPtr function )
{
  functions.push_front( function );
  return functions.begin();
};

void WindowFuncFactory::unregisterFunction( const char* name )
{
  std::remove_if( functions.begin(),
		  functions.end(),
		  boost::bind(&equivalence, _1, name) );
};

void WindowFuncFactory::unregisterFunction( iterator& it )
{
  functions.erase( it );
};
